From e54b0e627e15b90e86b5c566d22020fdba819b66 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 24 Feb 2010 10:47:34 +0000 Subject: [PATCH] [IA64] Support preemption in multicall After 19946:91407452cdb6, preemption in multicall may happen while HVM domains are running. It cause hypervisor's panic on ia64. This patch implements it in the same way to x86. Signed-off-by: KUWAMURA Shin'ya --- xen/arch/ia64/xen/hypercall.c | 65 +++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/xen/arch/ia64/xen/hypercall.c b/xen/arch/ia64/xen/hypercall.c index 24c25cbd83..b3193228b6 100644 --- a/xen/arch/ia64/xen/hypercall.c +++ b/xen/arch/ia64/xen/hypercall.c @@ -404,6 +404,18 @@ ia64_hypercall(struct pt_regs *regs) return IA64_NO_FAULT; } +#define next_arg(fmt, args) ({ \ + unsigned long __arg; \ + switch ( *(fmt)++ ) \ + { \ + case 'i': __arg = (unsigned long)va_arg(args, unsigned int); break; \ + case 'l': __arg = (unsigned long)va_arg(args, unsigned long); break; \ + case 'h': __arg = (unsigned long)va_arg(args, void *); break; \ + default: __arg = 0; BUG(); \ + } \ + __arg; \ +}) + unsigned long hypercall_create_continuation( unsigned int op, const char *format, ...) { @@ -415,43 +427,36 @@ unsigned long hypercall_create_continuation( va_list args; va_start(args, format); - if (test_bit(_MCSF_in_multicall, &mcs->flags)) - panic("PREEMPT happen in multicall\n"); // Not support yet - vcpu_set_gr(v, 15, op, 0); + if (test_bit(_MCSF_in_multicall, &mcs->flags)) { + dprintk(XENLOG_DEBUG, "PREEMPT happen in multicall\n"); + __set_bit(_MCSF_call_preempted, &mcs->flags); + for (i = 0; *p != '\0'; i++) + mcs->call.args[i] = next_arg(p, args); + } + else { + vcpu_set_gr(v, 15, op, 0); - for (i = 0; *p != '\0'; i++) { - switch ( *p++ ) - { - case 'i': - arg = (unsigned long)va_arg(args, unsigned int); - break; - case 'l': - arg = (unsigned long)va_arg(args, unsigned long); - break; - case 'h': - arg = (unsigned long)va_arg(args, void *); - break; - default: - arg = 0; - BUG(); + for (i = 0; *p != '\0'; i++) { + arg = next_arg(p, args); + vcpu_set_gr(v, 16 + i, arg, 0); } - vcpu_set_gr(v, 16 + i, arg, 0); - } - if (i >= 6) - panic("Too many args for hypercall continuation\n"); + if (i >= 6) + panic("Too many args for hypercall continuation\n"); - // Clean other argument to 0 - while (i < 6) { - vcpu_set_gr(v, 16 + i, 0, 0); - i++; - } + // Clean other argument to 0 + while (i < 6) { + vcpu_set_gr(v, 16 + i, 0, 0); + i++; + } - // re-execute break; - vcpu_decrement_iip(v); + // re-execute break; + vcpu_decrement_iip(v); - v->arch.hypercall_continuation = 1; + v->arch.hypercall_continuation = 1; + } + va_end(args); return op; } -- 2.30.2